﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Infrastructure;
using Microsoft.EntityFrameworkCore;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface;


namespace OpenAuth.App
{
    public class InspectViolationApp : BaseApp<InspectViolation>
    {
        private RevelanceManagerApp _revelanceApp;
        private IAuth _auth;

        /// <summary>
        /// 加载列表
        /// </summary>
        public TableData Load(QueryInspectViolationListReq request)
        {
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }

            var properties = loginContext.GetProperties("InspectViolation");

            if (properties == null || properties.Count == 0)
            {
                throw new Exception("当前登录用户没有访问该模块字段的权限，请联系管理员配置");
            }

            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrEmpty(request.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == request.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }

            var result = new TableData();
            var objs = UnitWork.Find<InspectViolation>(u => orgIdList.Contains(u.OrgId));
            if (!string.IsNullOrEmpty(request.key))
            {
                objs = objs.Where(u => u.InspectPlanId == request.key);
            }

            var propertyStr = string.Join(',', properties.Select(u => u.Key));
            result.columnHeaders = properties;
            result.data = objs.OrderByDescending(u => u.InspectSchedule.EndTime)
                .Skip((request.page - 1) * request.limit)
                .Take(request.limit).Select($"new ({propertyStr})");
            result.count = objs.Count();
            return result;
        }

        public TableData GetData(QueryInspectViolationListReq request)
        {
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }

            var properties = loginContext.GetProperties("InspectViolation");

            if (properties == null || properties.Count == 0)
            {
                throw new Exception("当前登录用户没有访问该模块字段的权限，请联系管理员配置");
            }

            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrEmpty(request.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == request.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }
            Expression<Func<InspectViolation, bool>> violationExpression = PredicateBuilder.True<InspectViolation>();
            violationExpression = violationExpression.And(u => orgIdList.Contains(u.OrgId));
            if (!string.IsNullOrEmpty(request.key))
            {
                violationExpression = violationExpression.And(u => u.InspectPlanId == request.key);
            }
            if (request.StartDate.HasValue)
            {
                violationExpression = violationExpression.And(u => u.CreateTime > request.StartDate.Value);
            }
            if (request.EndDate.HasValue)
            {
                var endDate = request.EndDate.Value.AddDays(1);
                violationExpression = violationExpression.And(u => u.CreateTime < endDate);
            }

            var result = new TableData();
            var dataList = new List<InspectViolationList>();
            var objs = UnitWork.Find(violationExpression);

            var data = objs.Include(u => u.InspectPlan)
                .Include(u => u.Org).Include(u => u.InspectSchedule)
                .OrderByDescending(u => u.CreateTime).Skip((request.page - 1) * request.limit).Take(request.limit).ToList();
            var userList = UnitWork.Find<User>(null).ToList();
            var planIdList = data.Select(u => u.InspectPlanId).ToList().Distinct();
            //var planContents = UnitWork.Find<InspectPlanContent>(u => planIdList.Contains(u.InspectPlanId));
            //var planAreas = UnitWork.Find<InspectArea>(null);
            foreach (var item in data)
            {
                var obj = new InspectViolationList
                {
                    Id = item.Id,
                    PlanName = item.InspectPlan?.Name,
                    OrgName = item.Org.Name,
                    Reason = item.Reason,
                    AuditMind = item.AuditMind,
                    IsViolation = item.IsViolation,
                    Status = item.Status,
                    Category = item.Category
                };
                string className = "";
                if (item.InspectSchedule != null)
                {
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        className = item.InspectSchedule.ClassName;
                    }
                    else
                    {
                        var startTime = item.InspectSchedule.StartTime;
                        var endTime = item.InspectSchedule.EndTime;
                        if (startTime.ToShortDateString() == endTime.ToShortDateString())
                        {
                            className = $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:HH:mm})";
                        }
                        else
                        {
                            className = $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:yyyy-MM-dd HH:mm})";
                        }
                    }
                    obj.ClassName = className;
                    string userNames = "";
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        string[] ids = item.InspectSchedule.Executor.Split("，");
                        var users = userList.Where(u => ids.Contains(u.Id)).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    else
                    {
                        var users = userList.Where(u => u.InspectTeam == item.InspectSchedule.ShiftTeam).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    obj.Person = userNames;
                }

                dataList.Add(obj);
            }
            result.data = dataList;
            result.count = objs.Count();
            return result;
        }

        public InspectViolationList GetDetail(string id)
        {
            var obj = UnitWork.Find<InspectViolation>(u => u.Id == id).Include(u => u.InspectPlan)
                .Include(u => u.Org).Include(u => u.InspectSchedule).FirstOrDefault();
            var planContents = UnitWork.Find<InspectPlanContent>(u => u.InspectPlanId == obj.InspectPlanId);
            var areaList = planContents.Select(u => u.InspectAreaId).ToList();
            var planArea = UnitWork.Find<InspectArea>(u => areaList.Contains(u.Id)).Select(u => u.Name).ToList();
            var userList = UnitWork.Find<User>(null).ToList();
            InspectViolationList result = new InspectViolationList
            {
                Id = obj.Id,
                PlanName = obj.InspectPlan.Name,
                OrgName = obj.Org.Name,
                Reason = obj.Reason,
                AuditMind = obj.AuditMind,
                IsViolation = obj.IsViolation,
                Status = obj.Status,
                Category = obj.Category
            };
            string className = "";
            if (string.IsNullOrEmpty(obj.InspectSchedule.ShiftTeam))
            {
                className = obj.InspectSchedule.ClassName;
            }
            else
            {
                var startTime = obj.InspectSchedule.StartTime;
                var endTime = obj.InspectSchedule.EndTime;
                if (startTime.ToShortDateString() == endTime.ToShortDateString())
                {
                    className = $"{obj.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:HH:mm})";
                }
                else
                {
                    className = $"{obj.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:yyyy-MM-dd HH:mm})";
                }
            }
            result.ClassName = className;
            string userNames = "";
            if (string.IsNullOrEmpty(obj.InspectSchedule.ShiftTeam))
            {
                string[] ids = obj.InspectSchedule.Executor.Split("，");
                var users = userList.Where(u => ids.Contains(u.Id)).Select(u => u.Name);
                userNames = string.Join(",", users);
            }
            else
            {
                var users = userList.Where(u => u.InspectTeam == obj.InspectSchedule.ShiftTeam).Select(u => u.Name);
                userNames = string.Join(",", users);
            }
            result.Person = userNames;
            result.Content = obj.Category == 2 ? obj.Reason + ":" + obj.LeakArea : obj.Reason + "：" + string.Join(",", planArea);
            return result;
        }

        public void Add(InspectViolation obj)
        {
            Repository.Add(obj);
        }

        public void Update(InspectViolation obj)
        {
            UnitWork.Update<InspectViolation>(u => u.Id == obj.Id, u => new InspectViolation
            {
                Status = 1,
                AuditMind = obj.AuditMind,
                IsViolation = obj.IsViolation
            });
            UnitWork.Save();
        }

        public List<InspectPlan> GetAllPlans()
        {
            return UnitWork.Find<InspectPlan>(null).ToList();
        }

        /// <summary>
        /// 违规报表查看具体信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public TableData GetReportDetailList(QueryInspectViolationListReq request)
        {
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }

            var properties = loginContext.GetProperties("InspectViolation");

            if (properties == null || properties.Count == 0)
            {
                throw new Exception("当前登录用户没有访问该模块字段的权限，请联系管理员配置");
            }

            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrEmpty(request.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == request.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }
            request.StartDate = request.StartDate?.ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                                DateTime.Now.AddDays(-6).ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            request.EndDate = request.EndDate?.AddDays(1).ToString("yyyy-MM-dd 00:00:00").ToDateTime() ??
                              DateTime.Now.AddDays(1).ToString("yyyy-MM-dd 00:00:00").ToDateTime();
            request.EndDate = request.EndDate?.AddMilliseconds(1);
            Expression<Func<InspectViolation, bool>> violationExpression = PredicateBuilder.True<InspectViolation>();
            violationExpression = violationExpression.And(u => orgIdList.Contains(u.OrgId))
                .And(u => u.InspectPlanId == request.PlanId).And(u => u.Category == request.Category)
                .And(u => u.CreateTime >= request.StartDate).And(u => u.CreateTime < request.EndDate);

            var result = new TableData();
            var dataList = new List<InspectViolationList>();
            var violationList = UnitWork.Find(violationExpression);

            var data = violationList.Include(u => u.InspectPlan)
                .Include(u => u.Org).Include(u => u.InspectSchedule)
                .OrderByDescending(u => u.CreateTime).ToList();
            var userList = UnitWork.Find<User>(null).ToList();
            foreach (var item in data)
            {
                var obj = new InspectViolationList
                {
                    Id = item.Id,
                    PlanName = item.InspectPlan?.Name,
                    OrgName = item.Org.Name,
                    Reason = item.Reason,
                    AuditMind = item.AuditMind,
                    IsViolation = item.IsViolation,
                    Status = item.Status,
                    Category = item.Category
                };
                if (item.InspectSchedule != null)
                {
                    var className = "";
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        className = item.InspectSchedule.ClassName;
                    }
                    else
                    {
                        var startTime = item.InspectSchedule.StartTime;
                        var endTime = item.InspectSchedule.EndTime;
                        if (startTime.ToShortDateString() == endTime.ToShortDateString())
                        {
                            className = $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:HH:mm})";
                        }
                        else
                        {
                            className = $"{item.InspectSchedule.ClassName}({startTime:yyyy-MM-dd HH:mm}至{endTime:yyyy-MM-dd HH:mm})";
                        }
                    }
                    obj.ClassName = className;
                    string userNames = "";
                    if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                    {
                        string[] ids = item.InspectSchedule.Executor.Split("，");
                        var users = userList.Where(u => ids.Contains(u.Id)).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    else
                    {
                        var users = userList.Where(u => u.InspectTeam == item.InspectSchedule.ShiftTeam).Select(u => u.Name);
                        userNames = string.Join(",", users);
                    }
                    obj.Person = userNames;
                }

                dataList.Add(obj);
            }
            result.data = dataList;
            result.count = violationList.Count();
            return result;
            //var propertyStr = string.Join(',', properties.Select(u => u.Key));
            //result.columnHeaders = properties;
            //result.data = obj.OrderByDescending(u => u.InspectSchedule.EndTime)
            //    .Skip((request.page - 1) * request.limit)
            //    .Take(request.limit).Select($"new ({propertyStr})");
            //result.count = obj.Count();
            //return result;
        }

        public string ExportExcel(QueryInspectViolationListReq request)
        {
            string filePath = "";
            var loginContext = _auth.GetCurrentUser();
            if (loginContext == null)
            {
                throw new CommonException("登录已过期", Define.INVALID_TOKEN);
            }
            List<string> orgIdList = new List<string>();
            if (!string.IsNullOrEmpty(request.OrgId))
            {
                var org = loginContext.Orgs.SingleOrDefault(u => u.Id == request.OrgId);
                foreach (Org item in loginContext.Orgs)
                {
                    if (item.CascadeId.Contains(org.CascadeId))
                    {
                        orgIdList.Add(item.Id);
                    }
                }
            }
            else
            {
                orgIdList = loginContext.Orgs.Select(u => u.Id).ToList();
            }
            Expression<Func<InspectViolation, bool>> violationExpression = PredicateBuilder.True<InspectViolation>();
            violationExpression = violationExpression.And(u => orgIdList.Contains(u.OrgId));
            if (!string.IsNullOrEmpty(request.key))
            {
                violationExpression = violationExpression.And(u => u.InspectPlanId == request.key);
            }
            if (request.StartDate.HasValue)
            {
                violationExpression = violationExpression.And(u => u.CreateTime > request.StartDate.Value);
            }
            if (request.EndDate.HasValue)
            {
                var endDate = request.EndDate.Value.AddDays(1);
                violationExpression = violationExpression.And(u => u.CreateTime < endDate);
            }
            var objs = UnitWork.Find(violationExpression).Include(u => u.InspectPlan)
                .Include(u => u.Org).Include(u => u.InspectSchedule).ToList();
            var result = new List<ExportInspectViolation>();
            if (!objs.Any())
                throw new Exception("数据为空");
            var userList = UnitWork.Find<User>(null).ToList();
            var planIdList = objs.Select(u => u.InspectPlanId).ToList().Distinct();
            var planContents = UnitWork.Find<InspectPlanContent>(u => planIdList.Contains(u.InspectPlanId));
            var planAreas = UnitWork.Find<InspectArea>(null);
            foreach (var item in objs)
            {
                var export = new ExportInspectViolation
                {
                    PlanName = item.InspectPlan?.Name,
                    OrgName = item.Org.Name,
                    Reason = item.Reason,
                    AuditMind = item.AuditMind,
                    IsViolation = item.IsViolation ? "是" : "否",
                };
                string className = "";
                if (item.InspectSchedule == null)
                    continue;
                if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                {
                    className = item.InspectSchedule.ClassName;
                }
                else
                {
                    var startTime = item.InspectSchedule.StartTime;
                    var endTime = item.InspectSchedule.EndTime;
                    if (startTime.ToShortDateString() == endTime.ToShortDateString())
                    {
                        className = $"{item.InspectSchedule.ClassName}({startTime.ToString("yyyy-MM-dd HH:mm")}至{endTime.ToString("HH:mm")})";
                    }
                    else
                    {
                        className = $"{item.InspectSchedule.ClassName}({startTime.ToString("yyyy-MM-dd HH:mm")}至{endTime.ToString("yyyy-MM-dd HH:mm")})";
                    }
                }
                export.ClassName = className;
                string userNames = "";
                if (string.IsNullOrEmpty(item.InspectSchedule.ShiftTeam))
                {
                    string[] ids = item.InspectSchedule.Executor.Split("，");
                    var users = userList.Where(u => ids.Contains(u.Id)).Select(u => u.Name);
                    userNames = string.Join(",", users);
                }
                else
                {
                    var users = userList.Where(u => u.InspectTeam == item.InspectSchedule.ShiftTeam).Select(u => u.Name);
                    userNames = string.Join(",", users);
                }
                export.Person = userNames;
                var areaIdList = planContents.Where(u => u.InspectPlanId == item.InspectPlanId).Select(u => u.InspectAreaId).ToList();
                var planArea = planAreas.Where(u => areaIdList.Contains(u.Id)).Select(u => u.Name).ToList();
                export.Content = item.Reason + string.Join(",", planArea);
                result.Add(export);
            }
            string[] colnumNames = new[] { "计划名称", "所属部门", "违规班次", "违规人员", "违规原因", "违规内容", "审核意见", "是否违规" };
            string exportFiled = AppContext.BaseDirectory + "Export";
            if (Directory.Exists(exportFiled) == false)//如果不存在就创建file文件夹
            {
                Directory.CreateDirectory(exportFiled);
            }
            string fileName = "巡检违规数据" + CommonHelper.CreateNo() + ".xlsx";
            string msg = "";
            var flag = OfficeHelper.ModelExportEPPlusExcel(result, exportFiled, fileName, colnumNames, ref msg);
            if (flag)
            {
                filePath = "/Export/" + fileName;
            }
            else
            {
                throw new Exception(msg);
            }
            return filePath;
        }

        public InspectViolationApp(IUnitWork unitWork, IRepository<InspectViolation> repository,
            RevelanceManagerApp app, IAuth auth) : base(unitWork, repository)
        {
            _revelanceApp = app;
            _auth = auth;
        }
    }
}